package org.skiplist2;


import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.TreeSet;

public class SkipListImplTest {

    public final Random random = new Random();

    @Test
    public void sizeTest() {
        int size = 10000;
        List<Integer> nums = getRandomList(size);

        SkipList<Integer> skipList = new SkipList<>();
        TreeSet<Integer> treeSet = new TreeSet<>();
        skipList.addAll(nums);
        treeSet.addAll(nums);
        Assert.assertEquals(treeSet.size(), skipList.size());
    }

    @Test
    public void isEmptyTest() {
        SkipList<Integer> skipList = new SkipList<>();
        Assert.assertTrue(skipList.isEmpty());
        skipList.add(1);
        Assert.assertFalse(skipList.isEmpty());
        skipList.remove(1);
        Assert.assertTrue(skipList.isEmpty());
    }

    @Test
    public void containsTest() {
        SkipList<Integer> skipList = new SkipList<>();
        int[] nums = new int[]{-99, -56, 1, 78, 265, Integer.MAX_VALUE};
        for (Integer num : nums) {
            skipList.add(num);
        }
        Assert.assertFalse(skipList.contains(Integer.MIN_VALUE));
        Assert.assertFalse(skipList.contains(-987867));
        Assert.assertFalse(skipList.contains(-98));
        Assert.assertFalse(skipList.contains(0));
        Assert.assertFalse(skipList.contains(264));
        Assert.assertFalse(skipList.contains(578676786));

        Assert.assertTrue(skipList.contains(-99));
        Assert.assertTrue(skipList.contains(-56));
        Assert.assertTrue(skipList.contains(1));
        Assert.assertTrue(skipList.contains(78));
        Assert.assertTrue(skipList.contains(265));
        Assert.assertTrue(skipList.contains(Integer.MAX_VALUE));
    }

    @Test
    public void addTest() {
        int size = 10000;
        int[] nums = getRandomArray(size);
        SkipList<Integer> skipList = new SkipList<>();
        TreeSet<Integer> set = new TreeSet<>();
        for (int num : nums) {
            skipList.add(num);
            set.add(num);
        }
        Assert.assertEquals(set.toString(), skipList.toString());
    }

    @Test
    public void removeTest() {
        int size = 10000;
        List<Integer> nums = getRandomList(size);
        SkipList<Integer> skipList = new SkipList<>();
        skipList.addAll(nums);
        for (Integer num : nums) {
            skipList.remove(num);
        }
        Assert.assertTrue(skipList.isEmpty());
    }

    @Test
    public void clearTest() {
        int size = 10000;
        List<Integer> nums = getRandomList(size);
        SkipList<Integer> skipList = new SkipList<>();
        skipList.addAll(nums);
        Assert.assertFalse(skipList.isEmpty());
        skipList.clear();
        Assert.assertTrue(skipList.isEmpty());
    }

    @Test
    public void addAllTest() {
        int size = 10000;
        List<Integer> nums = getRandomList(size);
        SkipList<Integer> skipList = new SkipList<>();
        TreeSet<Integer> set = new TreeSet<>();
        skipList.addAll(nums);
        set.addAll(nums);
        Assert.assertEquals(set.toString(), skipList.toString());
    }

    @Test
    public void firstTest() {
        int size = 1000;
        List<Integer> nums = getRandomList(size);
        SkipList<Integer> skipList = new SkipList<>();
        TreeSet<Integer> set = new TreeSet<>();
        skipList.addAll(nums);
        set.addAll(nums);
        Assert.assertEquals(set.first(), skipList.first());
    }

    @Test
    public void lastTest() {
        int size = 1000;
        List<Integer> nums = getRandomList(size);
        SkipList<Integer> skipList = new SkipList<>();
        TreeSet<Integer> set = new TreeSet<>();
        skipList.addAll(nums);
        set.addAll(nums);
        Assert.assertEquals(set.last(), skipList.last());
    }

    public int[] getRandomArray(int size) {
        int[] nums = new int[size];
        for (int i = 0; i < size; i++) {
            nums[i] = random.nextInt();
        }
        return nums;
    }

    public List<Integer> getRandomList(int size) {
        List<Integer> list = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            list.add(random.nextInt());
        }
        return list;
    }
}